package com.hnluchuan.bmjlearning.service;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import com.hnluchuan.bmjlearning.common.*;
import com.hnluchuan.bmjlearning.dao.UserDAO;
import com.hnluchuan.bmjlearning.dto.RoleDTO;
import com.hnluchuan.bmjlearning.dto.UserDTO;
import com.hnluchuan.bmjlearning.model.Agent;
import com.hnluchuan.bmjlearning.security.PasswordEncoder;
import com.hnluchuan.utils.exception.BizException;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.hnluchuan.bmjlearning.dao.CustomerDAO;
import com.hnluchuan.bmjlearning.model.Customer;
import com.hnluchuan.bmjlearning.dto.CustomerDTO;
import com.hnluchuan.core.support.Page;
import com.hnluchuan.utils.common.BeanMapper;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CustomerService extends BaseService {
	
	@Autowired
	private CustomerDAO customerDAO;
	@Autowired
	private UserDAO userDAO;
	@Autowired
	private ServicePackageService servicePackageService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserRoleService userRoleService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Value("${default.password}")
	protected String defaultPassword;
	@Value("${default.salt}")
	protected String defaultSalt;
	
	public List<CustomerDTO> find(CustomerDTO query, Page page) {
		List<Customer> models = customerDAO.find(query, page);
		List<CustomerDTO> dtos = toDTOs(models);
		return dtos;
	}
	
	public List<CustomerDTO> findAll() {
		return this.find(new CustomerDTO(), null);
	}
	
	public List<CustomerDTO> findAll(CustomerDTO query) {
		return this.find(query, null);
	}
	
	public List<CustomerDTO> find(Page page) {
		return this.find(new CustomerDTO(), page);
	}
	
	public List<CustomerDTO> find(int count) {
		Page page = new Page();
		page.setPage(1);
		page.setPageSize(count);
		return this.find(new CustomerDTO(), page);
	}
	
	public Long create(CustomerDTO dto) {
		Customer model = new Customer();
		toModel(model, dto);
		return customerDAO.create(model);
	}

	public CustomerDTO findByUserId(Long userId){
	    Customer model = customerDAO.findByUserId(userId);
		return toDTO(model);
	}

	public int getTodayNewlyEnrolledCustomersCount(Long agentId){
		return customerDAO.getTodayNewlyEnrolledCustomersCount(agentId);
	}

	public List<CustomerDTO> findByAgentId(Long agentId, Page page){
		List<Customer> models = customerDAO.findByAgentId(agentId, page);
		return toDTOs(models);
	}

	@Transactional(rollbackFor = Exception.class)
	public void enableOrDisable(Long userId, Long customerId, Integer status){
		int updatedCustomerCount = customerDAO.enableOrDisable(customerId, status);
		int updatedUserCount = userDAO.enableOrDisable(userId, status);
		if(updatedCustomerCount <= 0 || updatedUserCount <= 0){
			throw new BizException(ResultCode.OperationFailed.getRemark());
		}
	}

	public CustomerDTO load(Long id) {
	    Customer model = customerDAO.load(id);
	    return toDTO(model);
    }

	public void updateAllFields(CustomerDTO dto) {
		Customer model = customerDAO.load(dto.getId());
		toModel(model, dto);
		customerDAO.update(model);
    }

	public void deleteByIds(Long[] ids) {
		throw new RuntimeException("默认禁止删除，请确认是物理删除还是逻辑删除");
		/*
		if (ids != null) {
			for (Long id : ids) {
				customerDAO.deleteById(id);
			}
		} */
    }
	
	public void deleteById(Long id) {
		this.deleteByIds(new Long[] {id});
	}

	public CustomerDTO findOne(CustomerDTO query) {
		Customer model = customerDAO.findOne(query);
		return toDTO(model);
	}

	/**
	 * 根据文件流读取医生信息
	 *
	 * @param inputStream
	 * @return
	 * @throws Exception
	 */
	@Transactional
	public List<Customer> readCustomerByInputStream(InputStream inputStream) throws Exception{
		// 工作簿
		Sheet sheet = ExcelUtils.getWorkbook(inputStream).getSheetAt(0);
		List<Customer> list = new ArrayList<>();
		if (sheet != null) {
			// 当前时间
			Date now;
			// 最后一行
			int lastRowNum = sheet.getLastRowNum();
			if (lastRowNum == 0) {
				throw new BizException("医生信息为空！");
			}
			// 列索引
			Integer index = 0;
			// 行
			Row row;
			// 单元格
			Cell cell;
			// 单元格值
			String cellValue;
			Customer customer = null;
			for (int i = 1; i <= lastRowNum; i++) {
				now = new Date();
				customer = new Customer();
				row = sheet.getRow(i);
				// 机构名称
				customer.setOrgName(ExcelUtils.getCellValue(row, index++));
				// 医生名称
				customer.setName(ExcelUtils.getCellValue(row, index++));
				// 登录账号
				customer.setMobile(ExcelUtils.getCellValue(row, index++));
				// 身份证号
				customer.setIdCard(ExcelUtils.getCellValue(row, index++));
				// 职称
				customer.setTitle(ExcelUtils.getCellValue(row, index++));
				// 性别
				cell = row.getCell(index++);
				cellValue = ExcelUtils.getCellValue(cell);
				if (Sex.Male.getRemark().equals(cellValue)) {
					customer.setSex(Sex.Male.getValue());
				} else if (Sex.Female.getRemark().equals(cellValue)) {
					customer.setSex(Sex.Female.getValue());
				} else {
					customer.setSex(Sex.Unknow.getValue());
				}
				//通过导入新增的 默认都为未激活用户
				customer.setType(CustomerType.INACTIVE.getValue());
				index = 0;
				list.add(customer);
			}
		}
		return list;
	}

    @Transactional(rollbackFor = Exception.class)
    public int creatCustomer(List<Customer> customerList, Long agentId) {
        Iterator<Customer> iterator = customerList.iterator();
        Customer customer;
        int successNumber = 0;
        while (iterator.hasNext()) {
            customer = iterator.next();
            if (userDAO.findDuplicateCustomer(customer) != null) {
                continue;
            }
            String mobile = customer.getMobile();
            if (!StringUtils.isNumeric(mobile.trim()) || mobile.length() != 11) {
				continue;
			}
			UserDTO userDTO = new UserDTO();
			userDTO.setUsername(customer.getMobile());
			userDTO.setPassword(passwordEncoder.encodePassword(defaultPassword, defaultSalt));
			userDTO.setType(UserType.Clinic.getValue());
			userDTO.setDeleted(DeleteStatus.NotDeleted.getValue());
			userDTO.setNickName(customer.getOrgName());
			Long userId = userService.create(userDTO);
			UserDTO newlyCreatedUser = userService.load(userId);

			userRoleService.deleteByUserId(userId);
			RoleDTO roleDTO = roleService.findByCode(UserType.Clinic.getCode());
			userRoleService.addRole(userId, roleDTO.getId());

			customer.setStatus(CustomerStatus.Enabled.getValue());
			customer.setUser(newlyCreatedUser);
			customer.setAgent(new Agent(agentId));
			customerDAO.create(customer);
            successNumber++;
        }
        return successNumber;
    }


	public List<String> failedCustomerMobile(List<Customer> customerList) {

		Iterator<Customer> iterator = customerList.iterator();
		Customer customer;
		List<String> customerMobiles = new ArrayList<>();
		while (iterator.hasNext()) {
			customer = iterator.next();
			if (userDAO.findDuplicateCustomer(customer) != null) {
				customerMobiles.add(customer.getMobile());
				continue;
			}
			String mobile = customer.getMobile();
			if (!StringUtils.isNumeric(mobile.trim()) || mobile.length() != 11) {
				customerMobiles.add(customer.getMobile());
				continue;
			}
		}
		return customerMobiles;
	}
	
	private List<CustomerDTO> toDTOs(List<Customer> models) {
		if (CollectionUtils.isEmpty(models)) {
			return new ArrayList<CustomerDTO>(0);
		}
		List<CustomerDTO> dtos = new ArrayList<CustomerDTO>(models.size());
		for (Customer model : models) {
	        CustomerDTO dto = toDTO(model);
	        dtos.add(dto);
        }
	    return dtos;
    }
    
    private CustomerDTO toDTO(Customer model) {
		if (model == null) {
			return null;
		}
		CustomerDTO dto = BeanMapper.map(model, CustomerDTO.class);
		
		return dto;
	}
	
	private void toModel(Customer model, CustomerDTO dto) {
		BeanMapper.copy(dto, model);
    }
	
	@SuppressWarnings("unused")
	private List<Customer> toModels(List<CustomerDTO> dtos) {
		if (CollectionUtils.isEmpty(dtos)) {
			return new ArrayList<Customer>(0);
		}
		List<Customer> models = new ArrayList<Customer>(dtos.size());
		for (CustomerDTO dto : dtos) {
	        Customer model = new Customer();
	        toModel(model, dto);
	        models.add(model);
        }
		return models;
	}
}
